#-------------------------------------------------------------------------------
# Name:        CropDetcShortCircuit
# Purpose:
#
# Author:      Daiyusi
#
# Created:     14/07/2021
# Copyright:   (c) asus 2021
# Licence:     <your licence>
#-------------------------------------------------------------------------------

import numpy as np
from PIL import Image
# from PIL import ImageFont,ImageDraw
# import matplotlib.pyplot as plt

class CropDetc2:
    def avg_sum(self,im):
        # 面均值
        s = np.float(0)
        h, w = im.shape
        for i in range(h):
            for j in range(w):
                s = s * ((i * w + j) / (i * w + j + 1)) + im[i, j] / (i * w + j + 1)
        return s

    def max_avg_sum(self,im):
        # 线均值最大值
        h, w = im.shape
        maxs = 0
        for i in range(w):
            s = np.float(0)
            for j in range(h):
                s = s * (j / (j + 1)) + im[j, i] / (j + 1)
            if s > maxs:
                maxs = s
        return maxs

    def max2_avg_sum(self,im):
        # 半线均值最大值
        h, w = im.shape
        h2 = int(h / 2)
        maxs1 = self.max_avg_sum(im[0:h2, 0:])
        maxs2 = self.max_avg_sum(im[h2:, 0:])
        if maxs1 > maxs2:
            return maxs1
        else:
            return maxs2

        # s = (maxs1+maxs2)/2
        # return s

    # def max2_avg_sum(self,im):
    #     # 半线均值最大值
    #     h, w = im.shape
    #     h2 = int(h / 2)
    #     maxs1 = np.float(0)
    #     maxs2 = np.float(0)
    #     for i in range(w):
    #         s1 = np.float(0)
    #         s2 = np.float(0)
    #         for j in range(h):
    #             if j < h2:
    #                 s1 = s1 * (j / (j + 1)) + im[j, i] / (j + 1)
    #             else:
    #                 s2 = s2 * ((j - h2) / (j - h2 + 1)) + im[j, i] / (j - h2 + 1)
    #         if maxs1 < s1:
    #             maxs1 = s1
    #         if maxs2 < s2:
    #             maxs2 = s2
    #     s = (maxs1 + maxs2) / 2
    #     return s

    def max3_avg_sum(self,im):
        # (半)线均值最大值与面均值的加权平均
        s = np.float(0)
        s0 = self.avg_sum(im)
        s1 = self.max_avg_sum(im)
        s2 = self.max2_avg_sum(im)
        s = 0.7 * s2 + 0.3 * s0
        return s

    def uncovSearch(self, avgT, meanT):
        # 头尾板搜索计数,以p倍meanT为界
        n = [1, 1]  # [头,尾]
        p = 1.2

        for i in avgT[1:]:
            if i > p * meanT:
                n[0] = n[0] + 1
            else:
                break

        for i in avgT[36:0:-1]:
            if i > p * meanT:
                n[1] = n[1] + 1
            else:
                break

        # print('n:',n)
        return n

    def stdDetect(self, im, num):
        # 单槽板极短路检测,在有盖布时忽略前后端n个板极
        diag = [0 for i in range(num)]
        avgT = [0 for i in range(num)]
        h, w = im.shape
        # print(h,w)
        stp = w / num

        for i in range(num):
            p1 = int(i * stp)
            p2 = int((i + 1) * stp)
            subim = im[0:, p1:p2]
            avgT[i] = self.max3_avg_sum(subim)
            # print('avgT[', str(i + 1), ']:', avgT[i])

        meanT = np.mean(avgT)
        # stdT = np.std(avgT)
        #    print('meanT1:',meanT)

        difT = avgT - meanT
        uncov = [1 for i in range(num)]  # 有多层盖布处标记0
        num_uncov = num
        sum_uncov = 0
        for i in range(num):
            if difT[i] < -20:
                num_uncov = num_uncov - 1
                uncov[i] = 0
            sum_uncov = sum_uncov + uncov[i] * avgT[i]

        meanT = sum_uncov / num_uncov
        # print('meanT:',meanT)
        # 前后端n个板极忽略，不纳入均值计算
        n = [1, 1]
        if meanT < 180:
            n = self.uncovSearch(avgT,meanT)
            for i in range(-n[1], n[0]):
                if uncov[i] == 1:
                    # uncov[i] = 0
                    num_uncov = num_uncov - 1
                    sum_uncov = sum_uncov - avgT[i]
            meanT = sum_uncov / num_uncov

        difT = avgT - meanT

        print('n:', n)

        # 忽略前后n个板极，以及多层盖布后求标准差
        avgT_normal = []
        for i in range(n[0], num - n[1]):
            if uncov[i] == 1:
                avgT_normal.append(avgT[i])
        stdT = np.std(avgT_normal)


        print('meanT2:', meanT)
        print('stdT:', stdT)
        print('avgT:', np.round(avgT, 1))
        # print('difT:', np.round(difT, 1))



        k3, k2, k1 = [3.5, 2.5, 2.1]
        # 标准差过小
        if stdT < 0.1 * meanT:
            k3, k2, k1 = [3.5, 3, 2.5]
        if stdT < 0.05 * meanT:
            k3, k2, k1 = [5, 3.6, 2.8]

        for i in range(n[0], num - n[1]):
            if uncov[i] == 1:
                if difT[i] > k3 * stdT:
                    diag[i] = 3
                    if avgT[i] < 195:
                        diag[i] = 2
                    if avgT[i] < 160:
                        diag[i] = 1

                elif difT[i] > k2 * stdT:
                    diag[i] = 2
                    if avgT[i] < 170:
                        diag[i] = 1
                elif difT[i] > k1 * stdT:
                    diag[i] = 1
                    if meanT < 180 and avgT[i] > 205:
                        diag[i] = 2
                #         保证盖布且灰度值大于200可认为是疑似故障
                elif avgT[i] > 200:
                    diag[i] = 2

                if avgT[i] < 160:
                    diag[i] = 0

        # # 对最前、后n块板极中未被多层盖布遮挡的板极单独做阈值检测
        # # th = [160,170,180]
        th = [230, 240, 250]  # 两端板极检测阈值
        for i in range(-n[1], n[0]):
            if uncov[i] == 1:
                if avgT[i] > th[2]:
                    diag[i] = 3
                elif avgT[i] > th[1]:
                    diag[i] = 2
                elif avgT[i] > th[0]:
                    diag[i] = 1

        return diag

    def DistorRemove(self,im, k1, k2):
        # 桶形畸变矫正
        s = im.shape
        img = np.zeros(s)
        img = np.uint8(img)

        for l1 in range(s[0]):
            y = l1 - s[0] / 2

            for l2 in range(s[1]):
                x = l2 - s[1] / 2
                x1 = np.round(x * (1 + k1 * x * x + k2 * y * y))
                y1 = np.round(y * (1 + k1 * x * x + k2 * y * y))
                x1 = np.int(x1 + s[1] / 2)
                y1 = np.int(y1 + s[0] / 2)

                # 超出边界部分强制为0
                if x1 < 0 and x1 >= s[1] and y1 < 0 and y1 >= s[0]:
                    img[l1, l2] = 0;
                else:
                    img[l1, l2] = im[y1, x1]
        return img

    def CropOfBars(im):
        # 单槽自动裁剪（待完善）
        pass

    def DecInit(self,num1, num2, num3):
        # 生成key为‘槽号-板极号’，值为0的初始化字典
        diag = {}
        for i in range(num1[0], num1[1] + 1):
            for j in range(num2[0], num2[1] + 1):
                key = str(i) + '-' + str(j)
                diag[key] = [0 for i in range(num3)];
        return diag

    def ShortCircuitDetect(self, im, num3=38, num2=[1, 12], num1=[1, 2]):
        # 短路检测主程序
        im = im.convert('L')  # 转灰度图
        im = np.array(im)  # 图片转数组形式存储

        # 生成初始化字典,全0
        diag = self.DecInit(num1, num2, num3)

        # 桶形畸变矫正
        k1 = -3e-7;
        k2 = -4e-7;
        img = self.DistorRemove(im, k1, k2)
        # plt.imshow(img,cmap='gray',interpolation='bicubic')
        # plt.show()

        # 手动定位裁剪
        p = [513, 942, 4, 465]  # 整槽1、2的上下纵坐标位置
        # q = [[[21,14,95,370],[116,19,194,380],[214,20,300,389],[321,27,413,398],[429,27,519,409],[548,24,637,406],[668,34,755,418],[779,35,864,411],[899,30,967,405],[1010,32,1069,412],[1106,35,1170,406],[1205,32,1264,400]],[[13,32,114,416],[117,35,205,415],[223,26,310,416],[331,25,422,418],[447,24,543,419],[559,25,657,424],[679,26,777,425],[796,29,884,426],[905,36,1000,433],[1014,42,1099,436],[1120,53,1199,439],[1229,56,1277,444]],]
        q = [[[10, 13, 101, 370], [116, 16, 192, 377], [216, 18, 295, 388], [321, 22, 414, 395], [430, 24, 522, 404],
              [550, 27, 641, 408], [664, 30, 754, 411], [784, 32, 853, 409], [902, 34, 970, 413], [1010, 35, 1070, 405],
              [1109, 43, 1172, 402], [1202, 37, 1267, 402]],
             [[3, 33, 113, 418], [119, 28, 213, 416], [226, 29, 311, 416], [332, 26, 423, 418], [447, 24, 542, 419],
              [561, 26, 661, 422], [676, 27, 775, 425], [802, 34, 886, 428], [908, 39, 998, 431], [1017, 47, 1098, 435],
              [1123, 56, 1197, 440], [1229, 56, 1279, 444]]]
        # 所有单槽中的板极短路检测
        for i in range(num1[1] - num1[0] + 1):
            # 上、下整槽分离
            imBars = img[(p[2 * i] - 1):p[2 * i + 1], 0:]
            # 单槽分离及其板极短路检测
            for j in range(num2[1] - num2[0] + 1):
                im1bar = imBars[(q[i][j][1] - 1):q[i][j][3], (q[i][j][0] - 1):q[i][j][2]]
                # im1bar = np.resize(im1bar,[num3*10,100])
                # plt.imshow(im1bar,cmap='gray',interpolation='bicubic')
                # plt.show()
                print('***************************************' + str(i + 1) + '-' + str(j + 1))
                diagBars = self.stdDetect(im1bar.T, num3)  # 输入图片中板极纵向排列，0:正常 1:轻度 2:中度 3:重度
                key = str(i + 1) + '-' + str(j + 1)
                diag[key] = diagBars

                # plt.figure()
                # plt.subplot(2,1,1)
                # plt.imshow(im1bar.T, interpolation='bicubic')
                # plt.subplot(2,1,2)
                # plt.axis([1,num3,0,3])
                # plt.plot(list(range(1,num3+1)),diagBars,marker='*')
                # plt.savefig('SDC'+str(i+1)+'-'+str(j+1)+'.jpg',dpi=120)
                # plt.show()

        return diag

    def MyCheck(self, path):
        imPath = path
        # 'E:\\PythonProject\\SCD\\Images\\capture20210716_082701.jpg'
        # imPath = r'C:\RealPlayDemo\TestPic\capture20210714_105339.jpg'  # 'E:\\PythonProject\\ShortCircuitDetection\\Test003.jpg'
        num1 = [1, 2]  # 起始-结束整槽号
        num2 = [1, 12]  # 起始-结束单槽号
        num3 = 38  # number of plates in one electrobath
        # print(imPath)
        img = Image.open(imPath)  # read the image ( PIL image )
        diag = self.ShortCircuitDetect(img, num3, num2, num1)  # 短路检测
        # print(diag)
        print('欢迎使用测试版,打包发布使用SCDRelease！')
        return diag
        pass
